package com.wpml.netty.nio;

import java.io.IOException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * @Description
 * @Date 2021-07-16
 * @Author wangpei
 **/
public class TaskThread extends ThreadLocal<LinkedBlockingQueue<Channel>> implements Runnable {

    Selector selector = null;

    LinkedBlockingQueue<Channel> lbq = get();

    TaskThreadGroup workerGroup;

    public void setWorkerGroup(TaskThreadGroup worker) {
        this.workerGroup = worker;
    }


    @Override
    protected LinkedBlockingQueue<Channel> initialValue() {
        return new LinkedBlockingQueue<>();
    }

    TaskThread() {
        try {
            selector = Selector.open();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void run() {

        try {
            while (true) {
                // 检查是否有IO事件
                int num = selector.select(); // 阻塞

                if (num > 0) {
                    Set<SelectionKey> selectionKeys = selector.selectedKeys();
                    Iterator<SelectionKey> iterator = selectionKeys.iterator();
                    while (iterator.hasNext()) {
                        SelectionKey key = iterator.next();
                        iterator.remove();
                        if (key.isAcceptable()) {
                            System.out.println("=====isAcceptable=====");
                            acceptHandler(key);
                        } else if (key.isReadable()) {
                            readHandler(key);
                        } else if (key.isWritable()) {
                            System.out.println("=====isWritable=====");
                        } else {
                            key.cancel();
                            System.out.println("链接断开。。。");
                            break;
                        }
                    }
                }

                // 处理队列中任务
                if (!lbq.isEmpty()) {
                    Channel channel = lbq.take();
                    if (channel instanceof ServerSocketChannel) {
                        ServerSocketChannel server = (ServerSocketChannel) channel;
                        server.register(selector, SelectionKey.OP_ACCEPT); // 注册到selector 监听

                        System.out.println(Thread.currentThread().getName() + " register listen");
                    } else if (channel instanceof SocketChannel) {
                        SocketChannel client = (SocketChannel) channel;
                        ByteBuffer buffer = ByteBuffer.allocateDirect(4096);
                        client.register(selector, SelectionKey.OP_READ, buffer);
                        System.out.println(Thread.currentThread().getName() + " register client: " + client.getRemoteAddress());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    private void readHandler(SelectionKey key) {
        ByteBuffer buffer = (ByteBuffer) key.attachment();
        SocketChannel client = (SocketChannel) key.channel();
        buffer.clear();

        /*buffer.put(("服务端响应数据  默认值").getBytes());
        buffer.flip();
        try {
            System.out.println("发送数据");
            while (buffer.hasRemaining()) {
                client.write(buffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        buffer.clear();
        key.cancel();*/
//        buffer.put(("服务端响应数据  ").getBytes());

        while (true) {
            try {
                // 数据读取到buffer中
                int num = client.read(buffer);
                if (num > 0) {
                    buffer.put(("服务端响应数据  ").getBytes());
                    buffer.flip(); // 翻转
//                    byte[] bytes = new byte[buffer.limit()];
//                    String str = "默认值";
                    while (buffer.hasRemaining()) {
                        /*buffer.get(bytes,0, num);
                        str = new String(bytes, 0, bytes.length);
                        System.out.println("客户端发来的数据  " + str);*/

                        client.write(buffer);
                    }
                    buffer.clear();


                } else if (num == 0) {
                    break;
                } else {
                    // 客户端断开了
                    System.out.println("client : " + client.getRemoteAddress() + " 断开了......");
                    key.cancel();
                    break;
                }
            } catch (IOException e) {
                System.out.println("客户端异常断开");
                key.cancel();
                break;
            }
        }
    }

    private void acceptHandler(SelectionKey key) {
        try {
            ServerSocketChannel server = (ServerSocketChannel) key.channel();

            SocketChannel client = server.accept();

            client.configureBlocking(false);

            System.out.println("-------------------------------------------");
            System.out.println("新客户端：" + client.getRemoteAddress());
            System.out.println("-------------------------------------------");

            workerGroup.chooseSelector(client);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
